package com.wh.wisdomsite.xbox.zywl.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.wh.wisdomsite.xbox.common.Constants;
import com.wh.wisdomsite.xbox.common.reponse.CommonResult;
import com.wh.wisdomsite.xbox.core.session.impl.SimpleSession;
import com.wh.wisdomsite.xbox.pojo.zywl.GetGateInfoOut;
import com.wh.wisdomsite.xbox.pojo.zywl.UseTicketIn;
import com.wh.wisdomsite.xbox.pojo.zywl.UseTicketOut;
import com.wh.wisdomsite.xbox.utils.Const;
import com.wh.wisdomsite.xbox.utils.StringUtils;
import com.wh.wisdomsite.xbox.utils.server.connToserver_HttpClientClose;
import com.wh.wisdomsite.xbox.zywl.dao.ZywlGateGroupMapper;
import com.wh.wisdomsite.xbox.zywl.dao.ZywlGateMapper;
import com.wh.wisdomsite.xbox.zywl.dao.ZywlUserMapper;
import com.wh.wisdomsite.xbox.zywl.dao.ZywlUserTicketMapper;
import com.wh.wisdomsite.xbox.zywl.entity.ZywlGate;
import com.wh.wisdomsite.xbox.zywl.entity.ZywlGateGroup;
import com.wh.wisdomsite.xbox.zywl.entity.ZywlUser;
import com.wh.wisdomsite.xbox.zywl.entity.ZywlUserTicket;
import com.wh.wisdomsite.xbox.zywl.service.IZywlUserTicketService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 票务用户ServiceImpl
 * @author 谢泽鹏
 * @version V1.0
 * @Package com.wh.wisdomsite.xbox.vi.dao
 * @date 2018年09月05日 15:53
 * @Copyright 企业版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2018
 */
@Service("zywlUserTicketService")
@Transactional(rollbackFor = {Exception.class,RuntimeException.class})
public class ZywlUserTicketServiceImpl extends ServiceImpl<ZywlUserTicketMapper, ZywlUserTicket> implements IZywlUserTicketService {

    private static final Log logger = LogFactory.getLog(ZywlUserTicketServiceImpl.class);



    @Autowired
    private ZywlUserTicketMapper zywlUserTicketMapper;

    @Autowired
    private ZywlUserMapper zywlUserMapper;

    @Autowired
    private ZywlGateMapper zywlGateMapper;

    @Autowired
    private ZywlGateGroupMapper zywlGateGroupMapper;

    /**
     * 保存或更新
     * @param zywlUserTicket
     * @return
     */
    @Override
    public void saveOrUpdate(ZywlUserTicket zywlUserTicket) {
        try {
            String userTicketId = zywlUserTicket.getUserTicketId();
            logger.info("saveOrUpdate->>ZywlUserTicket->>票务编号： " + userTicketId);
            if(StringUtils.isNotEmpty(userTicketId)){
                //判断票务编号
                if(userTicketIdIsExits(userTicketId)){
                    //已存在[票务], 更新票务
                    EntityWrapper<ZywlUserTicket> entityWrapper = new EntityWrapper<>();
                    entityWrapper.eq("userTicketId", userTicketId);
                    zywlUserTicketMapper.update(zywlUserTicket, entityWrapper);
                    logger.info("saveOrUpdate->>ZywlUserTicket->>已存在[票务编号]->>执行更新");
                }else{
                    //不存在[票务], 添加票务
                    zywlUserTicket.setCreatDate(new Date());
                    zywlUserTicketMapper.insert(zywlUserTicket);
                    logger.info("saveOrUpdate->>ZywlUserTicket->>不存在[票务编号]->>执行添加");
                }
            }
        } catch (Exception e){
            e.printStackTrace();
            logger.info("saveOrUpdate->>ZywlUserTicket->>Exception： " + e.getMessage());
        }
    }


    /**
     * 判断票务是否存在
     * @param userTicketId 票务编号
     * @return
     */
    @Override
    @Transactional(propagation=Propagation.SUPPORTS)
    public boolean userTicketIdIsExits(String userTicketId) {
        ZywlUserTicket model = new ZywlUserTicket();
        model.setUserTicketId(userTicketId);
        ZywlUserTicket zywlUserTicket = zywlUserTicketMapper.selectOne(model);
        return null != zywlUserTicket ? true : false;
    }


    /**
     * 使用票务
     * @param in 票务入参
     * @return
     */
    @Override
    public CommonResult useTicket(UseTicketIn in) throws Exception {
        CommonResult commonResult = new CommonResult();
        try {
            ZywlUserTicket model = new ZywlUserTicket();
            //判断长度，13位则代表二维码扫描出来的userTicketId实际是identityId，先用identityId查询user，再调取使用身份证验证
            if(in.getUserTicketId().length() == 13){
                ZywlUser userModel = new ZywlUser();
                userModel.setIdentityId(in.getUserTicketId());
                userModel = zywlUserMapper.selectOne(userModel);
                in.setIdCard(userModel.getIdcardId());
                in.setPassType("Q");
                commonResult = useIdCard(in);
                return commonResult;
            }
            model.setUserTicketId(in.getUserTicketId());
            ZywlUserTicket zywlUserTicket = zywlUserTicketMapper.selectOne(model);
            if(null == zywlUserTicket){
                commonResult.setCode(Constants.CODE_FAIL);
                commonResult.setMessage("无效票务信息");
                return commonResult;
            }

            //非测试状态下，需要验证票据是否能使用,并且验证闸机与票是否对应
            if(!in.getOption().equals("test")){
                //检查票务的使用期限
                Date now = new Date();
                if(zywlUserTicket.getEndTime() != null && now.after(zywlUserTicket.getEndTime())){
                    commonResult.setCode(Constants.CODE_FAIL);
                    commonResult.setMessage("该票务已超出使用期限");
                    return commonResult;
                }
                if(zywlUserTicket.getBeginTime() != null && now.before(zywlUserTicket.getBeginTime())){
                    commonResult.setCode(Constants.CODE_FAIL);
                    commonResult.setMessage("该票务已超出使用期限");
                    return commonResult;
                }
                //检查票的剩余使用量
                if(0 == zywlUserTicket.getRule()){
                    commonResult.setCode(Constants.CODE_FAIL);
                    commonResult.setMessage("该票务无使用次数");
                    return commonResult;
                }
                //检查该闸机是否与票匹配
                ZywlGate zywlGateModel = new ZywlGate();
                zywlGateModel.setTransCode(in.getTransCode());
                ZywlGate findGate = zywlGateMapper.selectOne(zywlGateModel);
                if(findGate == null){
                    commonResult.setCode(Constants.CODE_FAIL);
                    commonResult.setMessage("没有此闸机信息");
                    return commonResult;
                }
                ZywlGateGroup gateGroupModel = new ZywlGateGroup();
                gateGroupModel.setId(findGate.getGgId());
                ZywlGateGroup findGateGroup = zywlGateGroupMapper.selectOne(gateGroupModel);
                if(findGateGroup == null){
                    commonResult.setCode(Constants.CODE_FAIL);
                    commonResult.setMessage("没有此闸机组信息");
                    return commonResult;
                }
                if(!Arrays.asList(zywlUserTicket.getDeviceGropCode().split(",")).contains(findGateGroup.getTransGroupCode())){
                    commonResult.setCode(Constants.CODE_FAIL);
                    commonResult.setMessage("此票不能通过此闸机设备，请确定入口是否正确");
                    return commonResult;
                }

                SimpleSession session = (SimpleSession) in.getXboxRequestContext().getOtherSession("ticket" + in.getUserTicketId());
                if(null != session){
                    Object object = session.getAttribute("useTicketOut");
                    if(null != object){
                        UseTicketOut useTicketOut = JSONObject.parseObject(JSONObject.toJSONString(object), UseTicketOut.class);
                        if(null != useTicketOut){
                            //(当前时间 - 使用时间) < 3分钟
                            if((new Date().getTime() - useTicketOut.getUseTime()) < 3 * 1000){
                                commonResult.setCode(Constants.CODE_FAIL);
                                commonResult.setMessage("票务已记录,请勿重复扫描");
                                return commonResult;
                            }
                        }
                    }
                }
            }

            EntityWrapper<ZywlUserTicket> ewZywlUserTicket = new EntityWrapper<>();
            ewZywlUserTicket.eq("userTicketId", in.getUserTicketId());
            ZywlUserTicket upZywlUserTicket = new ZywlUserTicket();
            upZywlUserTicket.setUseTime(new Date());
            //修改票务的剩余使用次数
            if(zywlUserTicket.getRule() > 0){
                upZywlUserTicket.setRule(zywlUserTicket.getRule() - 1);
            }
            upZywlUserTicket.setTicketState(2);
            upZywlUserTicket.setUsePer("");
            Integer falg = zywlUserTicketMapper.update(upZywlUserTicket, ewZywlUserTicket);
            if(falg > 0){
                commonResult.setCode(Constants.CODE_SUCCESS);
                commonResult.setMessage("票务使用成功，剩余使用次数:"+ (upZywlUserTicket.getRule() == null ? "无限" : upZywlUserTicket.getRule())+"次");

                //记录使用票务, 保存缓存中一天
                SimpleSession simpleSession = new SimpleSession();
                UseTicketOut useTicketOut = new UseTicketOut();
                useTicketOut.setUserTicketId(in.getUserTicketId());
                useTicketOut.setUseTime(new Date().getTime());
                simpleSession.setAttribute("useTicketOut", useTicketOut);
                in.getXboxRequestContext().addOtherSession("ticket" + in.getUserTicketId(), simpleSession, 24 * 3600 * 1000);
                //非测试状态下，需要向票务系统发送票据已使用的信息
                if(!in.getOption().equals("test")){
                    Map<String, String> paramMap = new HashMap<>();
                    paramMap.put("userTicketId", in.getUserTicketId());
                    paramMap.put("passType", in.getPassType() == null || org.apache.commons.lang3.StringUtils.isEmpty(in.getPassType()) ? "Q" : in.getPassType());
                    //调用票务平台的检票接口
                    String json = connToserver_HttpClientClose.sendPostRequest(Const.ZYWL_CHECKUSERTICKET, paramMap);
                }
            }else{
                commonResult.setCode(Constants.CODE_FAIL);
                commonResult.setMessage("票务使用失败");
            }
        } catch (Exception e){
            e.printStackTrace();
            commonResult.setCode(Constants.CODE_FAIL);
            commonResult.setMessage("票务使用异常");
            logger.error("useTicket->>Exception： " + e.getMessage());
            throw new Exception("useTicket->>Exception = " + e.getMessage());
        }
            return commonResult;
    }

    @Override
    public CommonResult useIdCard(UseTicketIn in) throws Exception {
        CommonResult commonResult = new CommonResult();
        try{
            ZywlUser model = new ZywlUser();
            model.setIdcardId(in.getIdCard());
            ZywlUser zywlUser = zywlUserMapper.selectOne(model);
            List<ZywlUserTicket> userTickets = null;
            EntityWrapper<ZywlUserTicket> ticketEntityWrapper = new EntityWrapper<>();
            //身份证通过模式，判断是否有票是直接绑定身份信息
            if(in.getPassType().equals("I")){
                ticketEntityWrapper.setEntity(new ZywlUserTicket());
                ticketEntityWrapper.eq("idcardId", in.getIdCard());
                userTickets = zywlUserTicketMapper.selectList(ticketEntityWrapper);
            }
            if(zywlUser == null && userTickets == null){
                //无此用户，不予通过
                commonResult.setCode(Constants.CODE_FAIL);
                commonResult.setMessage("查无此用户，无法验证通过");
                return commonResult;
            }
            //非测试状态下，查询用户是否有票
            if(!in.getOption().equals("test")){
                //查询此用户的票
                List<ZywlUserTicket> ticketList = new ArrayList<>();
                if(zywlUser != null){
                    EntityWrapper<ZywlUserTicket> ewTicket = new EntityWrapper<>();
                    ewTicket.setEntity(new ZywlUserTicket());
                    ewTicket.eq("uid", zywlUser.getId());
                    ewTicket.orderBy("creatDate", true);
                    ticketList = zywlUserTicketMapper.selectList(ewTicket);
                }
                //若直接绑定身份证的票集合不为空，则在ticketList下加入userTickets
                if(userTickets != null && !userTickets.isEmpty()){
                    ticketList.addAll(userTickets);
                }
                if(ticketList == null || ticketList.isEmpty()){
                    //用户无票，不予通过
                    commonResult.setCode(Constants.CODE_FAIL);
                    commonResult.setMessage("用户没有可用票，无法验证通过");
                    return commonResult;
                }
                for(ZywlUserTicket zywlUserTicket : ticketList){
                    in.setUserTicketId(zywlUserTicket.getUserTicketId());
                    in.setPassType(in.getPassType() == null || org.apache.commons.lang3.StringUtils.isEmpty(in.getPassType()) ? "I" : in.getPassType());
                    commonResult = useTicket(in);
                    if(commonResult.getCode().equals(Constants.CODE_SUCCESS)){
                        //使用成功，跳出循环
                        return commonResult;
                    }
                }
                //没有票可以通过
                commonResult.setCode(Constants.CODE_FAIL);
                commonResult.setMessage("验证失败，用户下没有票可以通过此设备。");
            }else{
                commonResult.setCode(Constants.CODE_SUCCESS);
                commonResult.setMessage("验证通过");
            }
        }catch (Exception e){
            e.printStackTrace();
            commonResult.setCode(Constants.CODE_FAIL);
            commonResult.setMessage("身份验证异常");
            logger.error("useIdCard->>Exception： " + e.getMessage());
            throw new Exception("useIdCard->>Exception = " + e.getMessage());
        }
        return commonResult;
    }

    @Override
    public CommonResult refundTicket(String userTicketId) throws Exception {
        CommonResult commonResult = new CommonResult();
        try{
            EntityWrapper<ZywlUserTicket> ew = new EntityWrapper<>();
            ew.setEntity(new ZywlUserTicket());
            ew.eq("userTicketId", userTicketId);
            int result = zywlUserTicketMapper.delete(ew);
            if(result > 0){
                //退票成功
                commonResult.setCode(Constants.CODE_SUCCESS);
                commonResult.setMessage("退票成功");
            }else{
                //退票失败
                commonResult.setCode(Constants.CODE_FAIL);
                commonResult.setMessage("此票务ID不能完成退票，退票失败");
            }
        }catch (Exception e){
            e.printStackTrace();
            commonResult.setCode(Constants.CODE_FAIL);
            commonResult.setMessage("用户退票异常");
            logger.error("refundTicket->>Exception： " + e.getMessage());
            throw new Exception("refundTicket->>Exception = " + e.getMessage());
        }
        return commonResult;
    }


}
